﻿using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using StaffWarsFm.Lib.Data;
using StaffWarsFm.Properties;

namespace StaffWarsFm.Discovery
{
    public class ServiceFinder
    {
        private Thread findThread;
        private UdpClient responseClient;

        public void Find()
        {
            findThread = new Thread(FindSpeakerMasters);
            findThread.Start();
        }

        public void Stop()
        {
            findThread.Abort();

            if (responseClient != null)
                responseClient.Close();
        }

        private void FindSpeakerMasters()
        {
            // Send the find command
            var sendUdpClient = new UdpClient(AddressFamily.InterNetwork);
            var groupIp = IPAddress.Parse(Settings.Default.DiscoveryMulticastGroupAddress);
            if (groupIp == null) throw new InvalidOperationException("Could not parse multicast group IP");
            var groupEndPoint = new IPEndPoint(groupIp, Settings.Default.DiscoveryMulticastGroupPort);

            sendUdpClient.Connect(groupEndPoint);
            var requestBytes = Encoding.UTF8.GetBytes(DiscoverCommands.FIND_SPEAKER_MASTER);

            // Create a port to listen back
            responseClient = new UdpClient(Settings.Default.DiscoveryReplyPort, AddressFamily.InterNetwork);

            sendUdpClient.Send(requestBytes, requestBytes.Length);

            while (true)
            {
                IPEndPoint remoteEndPoint = null;
                var responseData = responseClient.Receive(ref remoteEndPoint);
                var responseText = Encoding.UTF8.GetString(responseData);
                var responseReader = new StringReader(responseText);
                var address = responseReader.ReadLine();
                var lastFmName = responseReader.ReadLine();
                var displayName = responseReader.ReadLine();

                var details = new SpeakerMasterDetails
                {
                    Address = address,
                    User = new User
                    {
                        DisplayName = displayName,
                        UserName = lastFmName
                    }
                };

                var foundArgs = new SpeakerMasterFoundEventArgs { SpeakerMasterDetails = details };

                OnSpeakerMasterFound(foundArgs);
            }
        }

        public event EventHandler<SpeakerMasterFoundEventArgs> SpeakerMasterFound;

        protected virtual void OnSpeakerMasterFound(SpeakerMasterFoundEventArgs e)
        {
            var handler = SpeakerMasterFound;

            if (handler != null)
                handler(this, e);
        }
    }
}
